From 5a371d1a9c07b5cf1b2ec092356d099dacdb02f2 Mon Sep 17 00:00:00 2001 From: River Tarnell Date: Wed, 29 Jun 2005 03:37:57 +0000 Subject: [PATCH] refactor a little, cleanup, fix some display errors --- includes/PageHistory.php | 364 ++++++++++++++++++++++++++------------- 1 file changed, 241 insertions(+), 123 deletions(-) diff --git a/includes/PageHistory.php b/includes/PageHistory.php index 2e7ee14b23..3329684313 100644 --- a/includes/PageHistory.php +++ b/includes/PageHistory.php @@ -1,15 +1,24 @@ history() to print the + * history. + * * @package MediaWiki */ @@ -17,32 +26,55 @@ class PageHistory { var $mArticle, $mTitle, $mSkin; var $lastdate; var $linesonpage; - function PageHistory( $article ) { + var $mNotificationTimestamp; + + /** + * Construct a new PageHistory. + * + * @param Article $article + * @returns nothing + */ + function PageHistory($article) { + global $wgUser; + $this->mArticle =& $article; $this->mTitle =& $article->mTitle; + $this->mNotificationTimestamp = NULL; + $this->mSkin = $wgUser->getSkin(); } - # This shares a lot of issues (and code) with Recent Changes - + /** + * Print the history page for an article. + * + * @returns nothing + */ function history() { global $wgUser, $wgOut, $wgLang, $wgShowUpdatedMarker, $wgRequest, - $wgTitle, $wgUseValidation ; + $wgTitle, $wgUseValidation; - # If page hasn't changed, client can cache this + /* + * Allow client caching. + */ - if( $wgOut->checkLastModified( $this->mArticle->getTimestamp() ) ){ - # Client cache fresh and headers sent, nothing more to do. + if( $wgOut->checkLastModified( $this->mArticle->getTimestamp() ) ) + /* Client cache fresh and headers sent, nothing more to do. */ return; - } + $fname = 'PageHistory::history'; wfProfileIn( $fname ); + /* + * Setup page variables. + */ $wgOut->setPageTitle( $this->mTitle->getPrefixedText() ); $wgOut->setSubtitle( wfMsg( 'revhistory' ) ); $wgOut->setArticleFlag( false ); $wgOut->setArticleRelated( true ); $wgOut->setRobotpolicy( 'noindex,nofollow' ); + /* + * Fail if article doesn't exist. + */ $id = $this->mTitle->getArticleID(); if( $id == 0 ) { $wgOut->addHTML( wfMsg( 'nohistory' ) ); @@ -50,11 +82,20 @@ class PageHistory { return; } - $limit = $wgRequest->getInt('limit'); - if (!$limit) $limit = 50; + /* + * Extract limit, the number of revisions to show, and + * offset, the timestamp to begin at, from the URL. + */ + $limit = $wgRequest->getInt('limit', 50); $offset = $wgRequest->getText('offset'); - if (!strlen($offset) || !preg_match("/^[0-9]+$/", $offset)) $offset = 0; + /* Offset must be an integral. */ + if (!strlen($offset) || !preg_match("/^[0-9]+$/", $offset)) + $offset = 0; + + /* + * "go=last" means to jump to the last history page. + */ if (($gowhere = $wgRequest->getText("go")) !== NULL) { switch ($gowhere) { case "first": @@ -72,114 +113,60 @@ class PageHistory { } } - $firsturl = $wgTitle->escapeLocalURL("action=history&limit={$limit}&go=first"); - $lasturl = $wgTitle->escapeLocalURL("action=history&limit={$limit}"); - $firsttext = wfMsg("histfirst"); - $lasttext = wfMsg("histlast"); - - /* Check one extra row to see whether we need to show 'next' and diff links */ - $limitplus = $limit + 1; - - $namespace = $this->mTitle->getNamespace(); - $title = $this->mTitle->getText(); - $uid = $wgUser->getID(); - $db =& wfGetDB( DB_SLAVE ); - if ($uid && $wgShowUpdatedMarker ) - $notificationtimestamp = $db->selectField( 'watchlist', - 'wl_notificationtimestamp', - array( 'wl_namespace' => $namespace, 'wl_title' => $this->mTitle->getDBkey(), 'wl_user' => $uid ), - $fname ); - else $notificationtimestamp = false; - - $use_index = $db->useIndexClause( 'page_timestamp' ); - $revision = $db->tableName( 'revision' ); - - $limits = $offsets = ""; - $dir = 0; - if ($wgRequest->getText("dir") == "prev") - $dir = 1; - - list($dirs, $oper) = array("DESC", "<"); - if ($dir) { - list($dirs, $oper) = array("ASC", ">"); - } - - if ($offset) - $offsets .= " AND rev_timestamp $oper '$offset' "; - if ($limit) - $limits .= " LIMIT $limitplus "; - - $sql = "SELECT rev_id,rev_user," . - "rev_comment,rev_user_text,rev_timestamp,rev_minor_edit,rev_deleted ". - "FROM $revision $use_index " . - "WHERE rev_page=$id " . - $offsets . - "ORDER BY rev_timestamp $dirs " . - $limits; - $res = $db->query( $sql, $fname ); - - $revs = $db->numRows( $res ); - - if( $revs < $limitplus ) // the sql above tries to fetch one extra - $this->linesonpage = $revs; + /* + * Fetch revisions. + * + * If the user clicked "previous", we retrieve the revisions backwards, + * then reverse them. This is to avoid needing to know the timestamp of + * previous revisions when generating the URL. + */ + $direction = $this->getDirection(); + $revisions = $this->fetchRevisions($limit, $offset, $direction); + $navbar = $this->makeNavbar($revisions, $offset, $limit, $direction); + + /* + * We fetch one more revision than needed to get the timestamp of the + * one after this page (and to know if it exists). + * + * linesonpage stores the actual number of lines. + */ + if (count($revisions) < $limit + 1) + $this->linesonpage = count($revisions); else - $this->linesonpage = $revs - 1; + $this->linesonpage = count($revisions) - 1; - $atend = ($revs < $limitplus); - - $this->mSkin = $wgUser->getSkin(); - - $pages = array(); - $lowts = 0; - while ($line = $db->fetchObject($res)) { - $pages[] = $line; - } - if ($dir) $pages = array_reverse($pages); - if (count($pages) > 1) - $lowts = $pages[count($pages) - 2]->rev_timestamp; - else - $lowts = $pages[count($pages) - 1]->rev_timestamp; + /* Un-reverse revisions */ + if ($direction == DIR_PREV) + $revisions = array_reverse($revisions); + /* + * Print the top navbar. + */ + $s = $navbar; + $s .= $this->beginHistoryList(); + $counter = 1; - $prevurl = $wgTitle->escapeLocalURL("action=history&dir=prev&offset={$offset}&limit={$limit}"); - $nexturl = $wgTitle->escapeLocalURL("action=history&offset={$lowts}&limit={$limit}"); - $urls = array(); - foreach (array(20, 50, 100, 250, 500) as $num) { - $urls[] = "escapeLocalURL( - "action=history&offset={$offset}&limit={$num}")."\">".$wgLang->formatNum($num).""; + /* + * Print each revision, excluding the one-past-the-end, if any. + */ + foreach (array_slice($revisions, 0, $limit) as $i => $line) { + $first = !$i && $offset == 0; + $next = isset( $revisions[$i + 1] ) ? $revisions[$i + 1 ] : null; + $s .= $this->historyLine($line, $next, $counter, $this->getNotificationTimestamp(), $first); } - $bits = implode($urls, ' | '); - if ($offset) { - $prevtext = "".wfMsg("prevn", $limit).""; - $lasttext = "$lasttext"; - } else $prevtext = wfMsg("prevn", $limit); - if ($revs >= $limitplus) { - $nexttext = "".wfMsg("nextn", $limit).""; - $firsttext = "$firsttext"; - } else $nexttext = wfMsg("nextn", $limit); + /* + * End navbar. + */ + $s .= $this->endHistoryList(); + $s .= $navbar; - $firstlast = "($firsttext | $lasttext)"; - - $numbar = "$firstlast " . wfMsg("viewprevnext", $prevtext, $nexttext, $bits); - - $s = $numbar; - $s .= $this->beginHistoryList(); - $counter = 1; - foreach($pages as $i => $line) { - $first = ($counter == 1 && $offset == 0); - $next = isset( $pages[$i + 1] ) ? $pages[$i + 1 ] : null; - $s .= $this->historyLine( $line, $next, $counter, $notificationtimestamp, $first ); - $counter++; - } - $s .= $this->endHistoryList( !$atend ); - $s .= $numbar; - - # Validation line - if ( isset ( $wgUseValidation ) && $wgUseValidation ) { + /* + * Article validation line. + */ + if ($wgUseValidation) $s .= "

" . Validation::link2statistics ( $this->mArticle ) . "

" ; - } - + $wgOut->addHTML( $s ); wfProfileOut( $fname ); } @@ -204,7 +191,7 @@ class PageHistory { $s .= ''; return $s; } - + function submitButton( $bits = array() ) { return ( $this->linesonpage > 0 ) ? wfElement( 'input', array_merge( $bits, @@ -227,7 +214,7 @@ class PageHistory { $message[$msg] = wfMsg( $msg ); } } - + $link = $this->revLink( $row ); if ( 0 == $row->rev_user ) { @@ -253,9 +240,8 @@ class PageHistory { $s .= ' ' . wfElement( 'span', array( 'class' => 'minor' ), $message['minoreditletter'] ); } - $s .= $this->mSkin->commentBlock( $row->rev_comment, $this->mTitle ); - if ($notificationtimestamp && ($row->rev_timestamp >= $notificationtimestamp)) { + if ($this->getNotificationTimestamp() && ($row->rev_timestamp >= $this->getNotificationTimestamp())) { $s .= wfMsg( 'updatedmarker' ); } if( $row->rev_deleted ) { @@ -278,7 +264,7 @@ class PageHistory { 'oldid='.$row->rev_id ); } } - + function curLink( $row, $latest ) { global $wgUser; $cur = htmlspecialchars( wfMsg( 'cur' ) ); @@ -292,7 +278,7 @@ class PageHistory { 'diff=0&oldid=' . $row->rev_id ); } } - + function lastLink( $row, $next, $counter ) { global $wgUser; $last = htmlspecialchars( wfMsg( 'last' ) ); @@ -309,7 +295,7 @@ class PageHistory { ' tabindex="'.$counter.'"' ); } } - + function diffButtons( $row, $latest, $counter ) { global $wgUser; if( $this->linesonpage > 1) { @@ -321,7 +307,7 @@ class PageHistory { if( $row->rev_deleted && !$wgUser->isAllowed( 'undelete' ) ) { $radio['disabled'] = 'disabled'; } - + # XXX: move title texts to javascript if ( $latest ) { $first = wfElement( 'input', array_merge( @@ -351,10 +337,11 @@ class PageHistory { return ''; } } - + function getLastOffset($id, $step = 50) { $db =& wfGetDB(DB_SLAVE); - $sql = "SELECT rev_timestamp FROM revision WHERE rev_page = $id ORDER BY rev_timestamp ASC LIMIT $step"; + $sql = "SELECT rev_timestamp FROM revision WHERE rev_page = $id " . + "ORDER BY rev_timestamp ASC LIMIT $step"; $res = $db->query($sql, "getLastOffset"); $n = $db->numRows($res); @@ -365,6 +352,137 @@ class PageHistory { $obj = $db->fetchObject($res); return $obj->rev_timestamp; } + + function getDirection() { + global $wgRequest; + + if ($wgRequest->getText("dir") == "prev") + return DIR_PREV; + else + return DIR_NEXT; + } + + function fetchRevisions($limit, $offset, $direction) { + global $wgUser, $wgShowUpdatedMarker; + + /* Check one extra row to see whether we need to show 'next' and diff links */ + $limitplus = $limit + 1; + + $namespace = $this->mTitle->getNamespace(); + $title = $this->mTitle->getText(); + $uid = $wgUser->getID(); + $db =& wfGetDB( DB_SLAVE ); + + $use_index = $db->useIndexClause( 'page_timestamp' ); + $revision = $db->tableName( 'revision' ); + + $limits = $offsets = ""; + + if ($direction == DIR_PREV) + list($dirs, $oper) = array("ASC", ">="); + else /* $direction = DIR_NEXT */ + list($dirs, $oper) = array("DESC", "<="); + + if ($offset) + $offsets .= " AND rev_timestamp $oper '$offset' "; + + if ($limit) + $limits .= " LIMIT $limitplus "; + $page_id = $this->mTitle->getArticleID(); + + $sql = "SELECT rev_id,rev_user," . + "rev_comment,rev_user_text,rev_timestamp,rev_minor_edit,rev_deleted ". + "FROM $revision $use_index " . + "WHERE rev_page=$page_id " . + $offsets . + "ORDER BY rev_timestamp $dirs " . + $limits; + $res = $db->query($sql, "PageHistory::fetchRevisions"); + + $result = array(); + while (($obj = $db->fetchObject($res)) != NULL) + $result[] = $obj; +wfdebug("limits=$limits offset=$offsets got=".count($result)."\n"); + + return $result; + } + + function getNotificationTimestamp() { + global $wgUser, $wgShowUpdatedMarker; + + if ($this->mNotificationTimestamp !== NULL) + return $this->mNotificationTimestamp; + + if ($wgUser->getID() == 0 || !$wgShowUpdatedMarker) + return $this->mNotificationTimestamp = false; + + $db =& wfGetDB(DB_SLAVE); + + $this->mNotificationTimestamp = $db->selectField( + 'watchlist', + 'wl_notificationtimestamp', + array( 'wl_namespace' => $this->mTitle->getNamespace(), + 'wl_title' => $this->mTitle->getDBkey(), + 'wl_user' => $wgUser->getID() + ), + "PageHistory::getNotficationTimestamp"); + + return $this->mNotificationTimestamp; + } + + function makeNavbar($revisions, $offset, $limit, $direction) { + global $wgTitle, $wgLang; + + /* + * lowts is the timestamp of the first revision on this page. + * hights is the timestamp of the last revision. + */ + $atend = !(count($revisions) > $limit); +wfDebug("offset=$offset limit=$limit dir=$direction count=".count($revisions)."\n"); + $revisions = array_slice($revisions, 0, $limit); + + /* + * When we're displaying previous revisions, we need to reverse + * the array, because it's queried in reverse order. + */ + if ($direction == DIR_PREV) + $revisions = array_reverse($revisions); + + $lowts = $hights = 0; + + if (count($revisions)) { + $lowts = $revisions[0]->rev_timestamp; + $hights = $revisions[count($revisions) - 1]->rev_timestamp; + } + + $firsturl = $wgTitle->escapeLocalURL("action=history&limit={$limit}&go=first"); + $lasturl = $wgTitle->escapeLocalURL("action=history&limit={$limit}"); + $firsttext = wfMsg("histfirst"); + $lasttext = wfMsg("histlast"); + + $prevurl = $wgTitle->escapeLocalURL("action=history&dir=prev&offset={$lowts}&limit={$limit}"); + $nexturl = $wgTitle->escapeLocalURL("action=history&offset={$hights}&limit={$limit}"); + + $urls = array(); + foreach (array(20, 50, 100, 250, 500) as $num) { + $urls[] = "escapeLocalURL( + "action=history&offset={$offset}&limit={$num}")."\">".$wgLang->formatNum($num).""; + } + $bits = implode($urls, ' | '); + if (($direction == DIR_NEXT && $offset) || ($direction == DIR_PREV && !$atend)) { + $prevtext = "".wfMsg("prevn", $limit).""; + $lasttext = "$lasttext"; + } else $prevtext = wfMsg("prevn", $limit); + + if (!$atend || $direction == DIR_PREV) { + $nexttext = "".wfMsg("nextn", $limit).""; + $firsttext = "$firsttext"; + } else $nexttext = wfMsg("nextn", $limit); + + $firstlast = "($firsttext | $lasttext)"; + + return "$firstlast " . wfMsg("viewprevnext", $prevtext, $nexttext, $bits); + } } ?> -- 2.20.1